﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

//CID 0766 //2011.02.18 //Begin
namespace InfoJetSoft.Service.XPath.Exprs
{
    public class ExprEvaluator
    {
        private ICalculator calculator = null;
        private string xpath = null;
        //CID 0875 //2011.05.04 //Begin
        private IExpr expr = null;
        //CID 0875 //2011.05.04 //End

        public ExprEvaluator(ICalculator calc)
        {
            this.calculator = calc;
        }

        //CID 0875 //2011.05.04 //Begin
        public IExpr EvaluatedExpr
        {
            get
            {
                return this.expr;
            }
        }
        //CID 0875 //2011.05.04 //End

        private object Evaluate(object baseNode, string xpath)
        {
            this.xpath = xpath;
            
            ExprParser parser = new ExprParser(xpath);
            this.expr = parser.ParseExpr();
            //CID 0806 //2011.02.27 //Begin
            ExprContext context = new ExprContext();
            context.Calculator = this.calculator;
            //CID 0825 //2011.03.06 //Begin
            context.Calculator.Init();
            //CID 0825 //2011.03.06 //End
            context.Calculator.SetBaseNode(baseNode);
            context.Calculator.NewContext();
            object result = this.expr.Evaluate(context);
            context.Calculator.DeleteContext();
            //CID 0806 //2011.02.27 //End
            return result;
        }

        public INodeList EvaluateNodes(object node, string xpath)
        {
            object result = Evaluate(node, xpath);
            //CID 0766 //2011.02.25 //Begin
            if (result is INodeList)
            {
                return (INodeList)result;
            }
            else
            {
                return null;
            }
            //CID 0766 //2011.02.25 //End
        }

        public object EvaluateNode(object node, string xpath)
        {
            object result = Evaluate(node, xpath);
            //CID 0766 //2011.02.25 //Begin
            if (result is INodeList)
            {
                INodeList nodeList = (INodeList)result;
                if (nodeList.Count > 0)
                {
                    return nodeList.Get(0);
                }
                else
                {
                    return null;
                }
            }
            else
            {
                return null;
            }
            //CID 0766 //2011.02.25 //End
        }

        public object EvaluateValue(object node, string xpath)
        {
            object result = this.Evaluate(node, xpath);
            if (result is INodeList)
            {
                //CID 0766 //2011.02.25 //Begin
                INodeList nodeList = (INodeList)result;
                if(nodeList.Count > 0)
                {
                    object firstNode = nodeList.Get(0);
                    return this.calculator.GetNodeValue(firstNode);
                }
                else
                {
                    return null;
                }
                //CID 0766 //2011.02.25 //End
            }
            else
            {
                return result;
            }
        }
    }

    public enum Operator
    { 
        None = 0,
        Or = 1,
        And = 2,
        Equal = 3,
        NotEqual = 4,
        Lesser = 5,
        Greater = 6,
        LesserEqual = 7,
        GreaterEqual = 8,
        Add = 9,
        Subtract = 10,
        Unary = 11,
        Mul = 12,
        Div = 13,
        Mod = 14,
        Slash = 15,
        SlashSlash = 16,
        AxisAncestor = 17,
        AxisAncestorOrSelf = 18,
        AxisAttribute = 19,
        AxisChild = 20,
        AxisDescendant = 21,
        AxisDescendantOrSelf = 22,
        AxisFollowing = 23,
        AxisFollowingSibling = 24,
        AxisNamespace = 25,
        AxisParent = 26,
        AxisPreceding = 27,
        AxisPrecedingSibling = 28,
        AxisSelf = 29
    }
}
//CID 0766 //2011.02.18 //End